using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;


namespace Tools
{
    /// <summary>
    /// Gets the Signature / FingerPrint / Hardware Info of the PC
    /// </summary>
    /// <refference>
    /// </refference>
    public class HardwareInfo
        {
        private CmnForm caller = null;

        public HardwareInfo()
        {
        }


        public HardwareInfo(CmnForm caller)
        {
            this.caller = caller;
        }

        public void getHardWareSignature(ref DataStructures.HWInfo hwInfo)
        {
            hwInfo.cpuID = cpuId();
            hwInfo.biosID = biosId();
            hwInfo.diskID = diskId();
            hwInfo.baseID = baseId();
            hwInfo.videoID = videoId();
            hwInfo.macID = macId();
        }

        public void getHardWareSignature()
        {
            DataStructures.HWInfo hwInfo = new DataStructures.HWInfo();
            hwInfo.cpuID = cpuId();
            hwInfo.biosID = biosId();
            hwInfo.diskID = diskId();
            hwInfo.baseID = baseId();
            hwInfo.videoID = videoId();
            hwInfo.macID = macId();
            
            //inform the parent thread of the HW IDs
            if(caller != null)
                caller.Invoke(caller.HardwareNotifier, new Object[] {hwInfo});
        }

        private string identifier(string wmiClass, string wmiProperty, string wmiMustBeTrue)
        //Return a hardware identifier
        {
            string result = "";
            System.Management.ManagementClass mc = new System.Management.ManagementClass(wmiClass);
            System.Management.ManagementObjectCollection moc = mc.GetInstances();
            foreach (System.Management.ManagementObject mo in moc)
            {
                if (mo[wmiMustBeTrue].ToString() == "True")
                {

                    //Only get the first one
                    if (result == "")
                    {
                        try
                        {
                            result = mo[wmiProperty].ToString();
                            break;
                        }
                        catch
                        {
                        }
                    }

                }
            }
            return result;
        }

        private string identifier(string wmiClass, string wmiProperty)
        //Return a hardware identifier
        {
            string result = "";
            System.Management.ManagementClass mc = new System.Management.ManagementClass(wmiClass);
            System.Management.ManagementObjectCollection moc = mc.GetInstances();
            foreach (System.Management.ManagementObject mo in moc)
            {

                //Only get the first one
                if (result == "")
                {
                    try
                    {
                        result = mo[wmiProperty].ToString();
                        break;
                    }
                    catch
                    {
                    }
                }

            }
            return result;
        }

        private string cpuId()
        {
            //Uses first CPU identifier available in order of preference
            //Don't get all identifiers, as very time consuming
            string retVal = identifier("Win32_Processor", "UniqueId");
            if (retVal == "") //If no UniqueID, use ProcessorID
            {
                retVal = identifier("Win32_Processor", "ProcessorId");

                if (retVal == "") //If no ProcessorId, use Name
                {
                    retVal = identifier("Win32_Processor", "Name");


                    if (retVal == "") //If no Name, use Manufacturer
                    {
                        retVal = identifier("Win32_Processor", "Manufacturer");
                    }

                    //Add clock speed for extra security
                    retVal += identifier("Win32_Processor", "MaxClockSpeed");
                }
            }

            return retVal;
        }

        private string biosId()
        //BIOS Identifier
        {
            return    identifier("Win32_BIOS", "Manufacturer")
                    + identifier("Win32_BIOS", "SMBIOSBIOSVersion")
                    + identifier("Win32_BIOS", "IdentificationCode")
                    + identifier("Win32_BIOS", "SerialNumber")
                    + identifier("Win32_BIOS", "ReleaseDate")
                    + identifier("Win32_BIOS", "Version");
            
        }

        private string diskId()
        //Main physical hard drive ID
        {
            return    identifier("Win32_DiskDrive", "Model")
                    + identifier("Win32_DiskDrive", "Manufacturer")
                    + identifier("Win32_DiskDrive", "Signature")
                    + identifier("Win32_DiskDrive", "TotalHeads");
        }

        private string baseId()
        //Motherboard ID
        {
            return    identifier("Win32_BaseBoard", "Model")
                    + identifier("Win32_BaseBoard", "Manufacturer")
                    + identifier("Win32_BaseBoard", "Name")
                    + identifier("Win32_BaseBoard", "SerialNumber");
        }

        private string videoId()
        //Primary video controller ID
        {
            return    identifier("Win32_VideoController", "DriverVersion")
                    + identifier("Win32_VideoController", "Name");
        }

        private string macId()
        //First enabled network card ID
        {
            return identifier("Win32_NetworkAdapterConfiguration", "MACAddress", "IPEnabled");
        }

        private string pack(string text)
        //Packs the string to 8 digits
        {
            //return text;

            string retVal;
            int x = 0;
            int y = 0;
            foreach (char n in text)
            {
                y++;
                x += (n * y);
            }

            retVal = x.ToString() + "00000000";

            return retVal.Substring(0, 8);
        }
    }
}
